package com.jackrain.nea.wms.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.TypeUtils;
import com.aliyun.openservices.ons.api.Message;
import com.jackrain.nea.config.PropertiesConf;
import com.jackrain.nea.exception.NDSException;
import com.jackrain.nea.fc.dl.api.WmsTranOutSaveCmd;
import com.jackrain.nea.fc.dl.api.WmsTranOutUpdateCmd;
import com.jackrain.nea.util.ApplicationContextHandle;
import com.jackrain.nea.util.ReferenceUtil;
import com.jackrain.nea.util.ValueHolder;
import com.jackrain.nea.web.utils.ObjectToUtil;
import com.jackrain.nea.wms.mapper.WmsSqlMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 调拨出库单 改单->FC
 *
 * @author kangcong
 * @create 2018/10/15
 */
@Service("com.jackrain.fc.service.WmsTranOutUpdateService")
@Slf4j
public class WmsTranOutUpdateService implements BaseProcess {


    @Reference(version = "1.0", group = "dl")
    private WmsTranOutSaveCmd wmsTranOutSaveCmd;
    @Autowired
    private WmsSqlMapper wmsSqlMapper;
    @Autowired
    private PropertiesConf pconf;
    private final String TABLE_NAME = "WMS_T_TRAN";
    private final String TABLE_NAME_ITEM = "WMS_T_TRAN_ITEM";
    private final String WMS_T_OUT_NOTICES = "WMS_T_OUT_NOTICES";
    private static final int STATUS_ING = 00;
    private static final int STATUS_SUCCESS = 99;
    private static final int STATUS_FAILED = 90;

    @Override
    public ValueHolder process(JSONObject paramObject, Message message) throws Exception {

        ValueHolder valueHolder = new ValueHolder();

        if (null == paramObject || paramObject.size() <= 0) {
            return valueHolder;
        }

        List<HashMap> list = (List<HashMap>) paramObject.get("list");
        JSONObject retStr = requestData(list);
        valueHolder.put("retStr", retStr);

        return valueHolder;
    }

    @Override
    public List<HashMap> queryData(int pageSize) {

        WmsTranOutUpdateService wmsTranOutUpdateService = ApplicationContextHandle.getBean("com.jackrain.fc.service.WmsTranOutUpdateService");

        //分页查询数据 先查询未处理的
        String whereStr = " BILL_TYPE = 'NO' AND RECIVE_STATUS = 80 ";//00未处理
        String[] fields = new String[]{"ID", "WMS_BILL_NO", "BILL_TYPE", "DATE_OUT", "REMARK", "USERDEFINE1", "OBJID", "STATE"};
        String order = " WHERE " + whereStr + " ORDER BY ID ASC ";
        String limit = String.valueOf(pageSize);
        List<HashMap> list = wmsSqlMapper.select4(TABLE_NAME, fields, order, limit);

        if (list == null || list.size() <= 0) {
            return null;
        }

//        //未处理的没有再查询失败的
//        if (list == null || list.size() <= 0) {
//            whereStr = "BILL_TYPE = 'NO' AND RECIVE_STATUS = '90'  AND RETRY_COUNT < 5 ";//90失败
//            order = " WHERE " + whereStr + " ORDER BY FC_HANDLETIME ASC ";
//            list = wmsSqlMapper.select4(TABLE_NAME, fields, order, limit);
//
//            if (list == null || list.size() <= 0) {
//                return null;
//            }
//        }
        //修改为处理中
        wmsTranOutUpdateService.batchSave(list, STATUS_ING);
        log.info("WmsTranOutUpdateService--list-->{}",list);

        return list;
    }
    //查询原单号收货方编码
    private List<HashMap> queryOutData(String bill_no) {
        JSONObject whereKeys = new JSONObject();
        whereKeys.put("BILL_NO", bill_no);
        String[] fields = new String[]{"DEST_ECODE", "ORIG_ECODE"};
        List<HashMap> destEcodeList = wmsSqlMapper.select(WMS_T_OUT_NOTICES, fields, whereKeys);
        return destEcodeList;
    }
    //查询明细(明细不需要处理)
    private List<HashMap> queryItemData(Long bill_no) {
        JSONObject whereKeys = new JSONObject();
        whereKeys.put("BILL_ID", bill_no);
        String[] fields = new String[]{"ORIG_ECODE", "DEST_ECODE", "SKU", "QTY", "OWNER_ENAME", "OWNER_NAME", "MODIFIER_ENAME", "MODIFIER_NAME"};
        List<HashMap> list = wmsSqlMapper.select(TABLE_NAME_ITEM, fields, whereKeys);
        return list;
    }

    private JSONObject requestData(List<HashMap> list) {
        JSONObject retObject = new JSONObject();
        WmsTranOutUpdateService wmsTranOutUpdateService = ApplicationContextHandle.getBean("com.jackrain.fc.service.WmsTranOutUpdateService");

        if (list == null) {
            return retObject;
        }

        retObject.put("dataCount", list.size());

        //处理数据
        JSONArray postArray = new JSONArray();
        for (int i = 0; i < list.size(); i++) {

            JSONObject fixJo = new JSONObject();

            JSONObject jsonObject = new JSONObject(list.get(i));
            Long bill_id = jsonObject.getLong("ID");
            String bill_no = jsonObject.getString("USERDEFINE1");
            String message = "";
            List<HashMap> itemList = new ArrayList<>();
            try {
                //查询原单号收货方编码
                List<HashMap> destEcodeList = queryOutData(bill_no);
                log.info("WmsTranOutUpdateService--destEcodeList-->{}",destEcodeList);

                if((destEcodeList != null) && (destEcodeList.size()> 0)){
                    //查询明细
                    itemList = queryItemData(bill_id);
                    log.info("WmsTranOutUpdateService--itemList-->{}",itemList);

                    String destEcode = (String) destEcodeList.get(0).get("DEST_ECODE");
                    String origEcode = (String) destEcodeList.get(0).get("ORIG_ECODE");
                    String destEcodeItem = (String) itemList.get(0).get("DEST_ECODE");
                    String origEocdeItem = (String) itemList.get(0).get("ORIG_ECODE");
                    log.debug("WmsTranOutUpdateService--destEcode:origEcode-->"+destEcode+":"+origEcode+"-->"+destEcodeItem+":"+origEocdeItem);
                    //判断收货方编码和原单收货方编码是否相同
                    if (!((destEcode.equals(destEcodeItem))&&(origEcode.equals(origEocdeItem)))) {
                        message = "中间表收发货方编码和原单不一致";
                        throw new NDSException("中间表收发货方编码和原单不一致");
                    }
                }else{
                    message = "出库通知中没有该记录";
                    saveWmsErrorEcode(bill_id,message);
                    continue;
                }
            }catch (Exception e){
                saveWmsErrorEcode(bill_id,message);
                continue;
            }
            //判断明细
            try {
                if (itemList == null || itemList.size() <= 0) {
                    throw new NDSException("调拨出0库改单明细为空不处理！");
                }
                JSONArray itemArray = listToJsonarray(itemList);
                fixJo.put("DL_B_TRAN", jsonObject);
                JSONArray itemArrayData = new JSONArray();
                itemArrayData.add(itemArray);
                fixJo.put("DL_B_TRAN_ITEM_SKU", itemArrayData);
                postArray.add(fixJo);

            } catch (Exception e) {
                saveWmsErrorDetail(bill_id);
                continue;
            }
        }
        try {
            JSONObject returnJson = doPost(postArray);
            log.info("WmsTranOutUpdateService--returnJson-->{}",returnJson);

            retObject.put("ret", returnJson);
            if (returnJson == null || returnJson.size() <= 0) {
                //修改为失败
                wmsTranOutUpdateService.batchSave(list, STATUS_FAILED);
                throw new NDSException("服务端没有数据，请求参数" + postArray.toJSONString());
            } else {
                Long code = returnJson.getLong("code");
                if (code == null || code != 0) {
                    //再修改为成功
                    JSONArray success = returnJson.getJSONArray("success");
                    if (success != null && success.size() > 0) {
                        wmsTranOutUpdateService.batchSuccSave(success, STATUS_SUCCESS);
                    }
                    //更新中间表数据
                    JSONArray errorArray = returnJson.getJSONArray("error");
                    wmsTranOutUpdateService.saveWmsError(errorArray);
                    throw new NDSException("服务端保存出错，" + returnJson);
                }

                if (0 == code) {
                    JSONArray success = returnJson.getJSONArray("success");
                    wmsTranOutUpdateService.batchSuccSave(success, STATUS_SUCCESS);
                }
            }
        } catch (Exception e) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            if ((e instanceof NDSException)) {
                throw e;
            } else {
                //修改为失败
                wmsTranOutUpdateService.batchSave(list, STATUS_FAILED);
                throw new NDSException(sw.toString());
            }
        }

        return retObject;
    }

    private JSONObject doPost(JSONArray postArrayRow) {
        long startTime = System.currentTimeMillis();

        JSONObject data = new JSONObject();
        data.put("data", postArrayRow);

        ValueHolder result = new ValueHolder();
        try {
            HashMap map = new HashMap(1);
            map.put("param", data);
            Object o = ReferenceUtil.refer(ApplicationContextHandle.getApplicationContext(), "com.jackrain.nea.fc.dl.api.WmsTranOutUpdateCmd", "dl", "1.0");
            result = ((WmsTranOutUpdateCmd) o).execute(map);

            if (result == null) {
                result = new ValueHolder();
                result.put("code", -1);
                result.put("error", "服务错误：返回为空");
            }
            if (result.get("code") == null) {
                result.put("code", 0);
            }

        } catch (Exception e) {
            result.put("code", -1);
            if (e instanceof NDSException) {
                result.put("error", "服务错误：" + e.getMessage());
            } else {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                result.put("error", "服务错误：" + sw.toString());
            }
        }

        double spendTime = (double) (System.currentTimeMillis() - startTime) / 1000.0D;
        result.put("doPostSpendTime", spendTime);
        return result.toJSONObject();

    }
    public void batchSave(List<HashMap> list, int status) {

        if (list == null) {
            return;
        }
        //修改状态
        for (int i = 0; i < list.size(); i++) {
            JSONObject jsonObject = new JSONObject(list.get(i));
            if (jsonObject == null) {
                continue;
            }
            Long bill_no = jsonObject.getLong("ID");
            if (ObjectToUtil.isNullOREmpty(String.valueOf(bill_no))) {
                continue;
            }
            JSONObject setKeys = new JSONObject();
            // 累计重试次数
            setKeys.put("RECIVE_STATUS", status);//
            setKeys.put("FC_HANDLETIME", new Timestamp(System.currentTimeMillis()));//处理时间
            if (STATUS_SUCCESS == status) {
                setKeys.put("ERROR_LOG", "");//
            }
            if (STATUS_FAILED == status) {
                int retrycount = retryCount(bill_no);
                setKeys.put("RETRY_COUNT", retrycount + 1);
            }
            JSONObject whereKeys = new JSONObject();
            whereKeys.put("ID", bill_no);
            wmsSqlMapper.update(TABLE_NAME, setKeys, whereKeys);
        }

    }

    /**
     * 状态为失败时调用累计重试次数
     */
    private int retryCount(Long bill_no) {

        JSONObject whereKeys = new JSONObject();
        whereKeys.put("ID", bill_no);

        List<HashMap> retryList = wmsSqlMapper.select(TABLE_NAME, new String[]{"RETRY_COUNT"}, whereKeys);
        HashMap hashMap = retryList.get(0);
        int retrycount = TypeUtils.castToInt(hashMap.get("RETRY_COUNT"));

        return retrycount;

    }

    public void batchSave(JSONArray dataArray, int status) {

        if (dataArray == null) {
            return;
        }
        //修改状态
        for (int i = 0; i < dataArray.size(); i++) {
            String bill_no = dataArray.getString(i);
            if (ObjectToUtil.isNullOREmpty(bill_no)) {
                continue;
            }
            JSONObject setKeys = new JSONObject();
            setKeys.put("RECIVE_STATUS", status);//
            setKeys.put("FC_HANDLETIME", new Timestamp(System.currentTimeMillis()));//处理时间
            if (STATUS_SUCCESS == status) {
                setKeys.put("ERROR_LOG", "");//
            }
            JSONObject whereKeys = new JSONObject();
            whereKeys.put("ID", bill_no);
            wmsSqlMapper.update(TABLE_NAME, setKeys, whereKeys);
        }

    }

    public void batchSuccSave(JSONArray dataArray, int status) {

        if (dataArray == null) {
            return;
        }
        //修改状态
        for (int i = 0; i < dataArray.size(); i++) {

            JSONObject dataJO = dataArray.getJSONObject(i);
            Long bill_no = dataJO.getLong("id");
            Long objid = dataJO.getLong("objid");
            int state = dataJO.getInteger("state");
            if (ObjectToUtil.isNullOREmpty(String.valueOf(bill_no))) {
                continue;
            }
            JSONObject setKeys = new JSONObject();
            setKeys.put("RECIVE_STATUS", status);//
            setKeys.put("objid", objid);
            setKeys.put("state", state);
            setKeys.put("FC_HANDLETIME", new Timestamp(System.currentTimeMillis()));//处理时间
            if (STATUS_SUCCESS == status) {
                setKeys.put("ERROR_LOG", "");//
            }
            JSONObject whereKeys = new JSONObject();
            whereKeys.put("ID", bill_no);
            wmsSqlMapper.update(TABLE_NAME, setKeys, whereKeys);
        }
    }
    public void saveWmsErrorEcode(Long bill_id,String message) {
        JSONObject whereKeys = new JSONObject();
        whereKeys.put("id", bill_id);
        int retryCount = retryCount(bill_id);
        JSONObject setKeys = new JSONObject();
        setKeys.put("ERROR_LOG", message);
        setKeys.put("RECIVE_STATUS", STATUS_FAILED);//失败
        setKeys.put("FC_HANDLETIME", new Timestamp(System.currentTimeMillis()));//处理时间
        setKeys.put("RETRY_COUNT", retryCount + 1);
        wmsSqlMapper.update(TABLE_NAME, setKeys, whereKeys);
    }
    public void saveWmsErrorDetail(Long bill_id) {

        JSONObject whereKeys = new JSONObject();
        whereKeys.put("id", bill_id);
        int retryCount = retryCount(bill_id);
        JSONObject setKeys = new JSONObject();
        setKeys.put("error_log", "明细不能为空！");
        setKeys.put("recive_status", STATUS_FAILED);//失败
        setKeys.put("fc_handletime", new Timestamp(System.currentTimeMillis()));//处理时间
        setKeys.put("retry_count", retryCount + 1);
        wmsSqlMapper.update(TABLE_NAME, setKeys, whereKeys);
    }

    //    @Transactional(rollbackFor = Exception.class)
    public void saveWmsError(JSONArray errorArray) {

        if (errorArray == null) {
            return;
        }
        for (int i = 0; i < errorArray.size(); i++) {
            JSONObject errorObject = errorArray.getJSONObject(i);
            if (errorObject == null) {
                continue;
            }
            Long bill_no = errorObject.getLong("id");
            Long objid = errorObject.getLong("objid");
            int state = errorObject.getInteger("state");

            if (ObjectToUtil.isNullOREmpty(String.valueOf(bill_no))) {
                continue;
            }
            JSONObject whereKeys = new JSONObject();
            whereKeys.put("id", bill_no);
            int retryCount = retryCount(bill_no);
            String msg = errorObject.getString("message");
            JSONObject setKeys = new JSONObject();
            if (!ObjectToUtil.isNullOREmpty(msg)) {
                setKeys.put("error_log", msg);//
            }
            setKeys.put("recive_status", STATUS_FAILED);//失败
            setKeys.put("fc_handletime", new Timestamp(System.currentTimeMillis()));//处理时间
            setKeys.put("retry_count", retryCount + 1);
            setKeys.put("objid", objid);
            setKeys.put("state", state);
            wmsSqlMapper.update(TABLE_NAME, setKeys, whereKeys);

        }
    }


    private void handleTimeOut(long timeMillis) {

        //修改状态为失败
        JSONObject setKeys = new JSONObject();
        setKeys.put("RECIVE_STATUS", STATUS_FAILED);//
        setKeys.put("FC_HANDLETIME", new Timestamp(System.currentTimeMillis()));//处理时间
        String whereStr = "RECIVE_STATUS = '" + STATUS_ING + "' AND FC_HANDLETIME < '" + new Timestamp(System.currentTimeMillis() - timeMillis) + "'";
        wmsSqlMapper.update3(TABLE_NAME, setKeys, whereStr);
    }

    /**
     * list转jsonarray
     *
     * @param mapList
     * @return jsonArray
     */
    public JSONArray listToJsonarray(List<HashMap> mapList) {

        JSONArray jsonArray = new JSONArray();
        for (int i = 0; i < mapList.size(); i++) {
            HashMap map = (HashMap) mapList.get(i);
            JSONObject jsonObject = new JSONObject(map);
            JSONObject param = JSON.parseObject(JSON.toJSONStringWithDateFormat(jsonObject, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteMapNullValue), Feature.OrderedField);
            jsonArray.add(param);
        }
        return jsonArray;
    }


}
